package com.morn.fanfou.api;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;

import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.signature.HmacSha1MessageSigner;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import android.content.Context;
import android.net.http.AndroidHttpClient;
import android.util.Log;

import com.morn.fanfou.exception.FanfouNetException;
import com.morn.fanfou.model.OAuthToken;
import com.morn.fanfou.util.Constants;

public abstract class FanfouSupport {
	public static final String BASEURL = "http://api.fanfou.com";
	protected final HttpClient httpClient = AndroidHttpClient.newInstance("fanfou");
	private static final String TAG = "httpClient";
	private boolean cancelled = false;
	protected Context context;

	public FanfouSupport(Context context) {
		this.context = context;
	}

	public String doHttpGet(String url, NameValuePair... nameValuePairs) throws FanfouNetException {
		url = BASEURL + url;
		String returnStr = "";
		HttpGet httpGet = createHttpGet(url, nameValuePairs);
		httpGet.setHeader("Accept-Encoding", "gzip,deflate");
		HttpEntity entity = null;
		HttpContext localContext = new BasicHttpContext();
		int statusCode = 0;
		try {
			HttpResponse response = httpClient.execute(httpGet, localContext);
			statusCode = response.getStatusLine().getStatusCode();
			Log.i(TAG, "statusCode=" + statusCode);
			if (statusCode == HttpStatus.SC_OK) {
				entity = response.getEntity();
				if (entity != null) {
					InputStream is = entity.getContent();
					if (is == null) {
						throw new FanfouNetException("Connextion error:InputStream is NULL");
					}
					GZIPInputStream gzin = new GZIPInputStream(is);
					Reader reader = new InputStreamReader(gzin, "UTF-8");
					CharArrayBuffer buffer = new CharArrayBuffer(4096);

					char[] tmp = new char[1024];
					int l;
					while ((l = reader.read(tmp)) != -1) {
						if (cancelled) {
							httpGet.abort();
						}
						buffer.append(tmp, 0, l);
					}
					returnStr = buffer.toString();
				} else {
					throw new FanfouNetException("Connextion error:entity is NULL");
				}
			} else {
				entity = response.getEntity();
				if (entity != null) {
					InputStream is = entity.getContent();
					if (is == null) {
						throw new FanfouNetException("Connextion error:InputStream is NULL");
					}
					GZIPInputStream gzin = new GZIPInputStream(is);
					Reader reader = new InputStreamReader(gzin, "UTF-8");
					CharArrayBuffer buffer = new CharArrayBuffer(4096);

					char[] tmp = new char[1024];
					int l;
					while ((l = reader.read(tmp)) != -1) {
						if (cancelled) {
							httpGet.abort();
						}
						buffer.append(tmp, 0, l);
					}
					JSONObject errorJSON = new JSONObject(buffer.toString());
					String errorStr = errorJSON.getString("error");
					throw new FanfouNetException(errorStr);
				} else {
					throw new FanfouNetException("Connextion error:Connextion entity is NULL");
				}

			}

		} catch (Exception e) {
			e.printStackTrace();
			// if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
			// httpClient.getCookieStore().clear();
			// }
			throw new FanfouNetException(e.getMessage());
		} finally {
			if (httpGet != null && !httpGet.isAborted()) {
				httpGet.abort();
			}
		}
		return returnStr;
	}

	public String doHttpPost(String url, NameValuePair... nameValuePairs) throws FanfouNetException {
		url = BASEURL + url;
		HttpPost httpPost = createHttpPost(url, nameValuePairs);
		String returnStr = "";
		int statusCode;
		try {
			HttpResponse response = httpClient.execute(httpPost);
			statusCode = response.getStatusLine().getStatusCode();
			Log.i(TAG, "statusCode=" + statusCode);
			if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_ACCEPTED) {

				HttpEntity entity = response.getEntity();
				if (entity == null) {
					throw new FanfouNetException("Connextion error:entity is NULL");
				}
				returnStr = EntityUtils.toString(entity);
				Log.i("Test", "returnStr=" + returnStr);
			} else {
				HttpEntity entity = response.getEntity();
				if (entity == null) {
					throw new FanfouNetException("Connextion error:entity is NULL");
				}
				JSONObject errorJSON = new JSONObject(EntityUtils.toString(entity));
				String errorStr = errorJSON.getString("error");
				throw new FanfouNetException(errorStr);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new FanfouNetException(e.getMessage());
		} finally {
			if (httpPost != null && !httpPost.isAborted()) {
				httpPost.abort();
			}
		}

		return returnStr;
	}

	protected HttpGet createHttpGet(String url, NameValuePair... nameValuePairs) {
		String query = URLEncodedUtils.format(stripNulls(nameValuePairs), HTTP.UTF_8);
		HttpGet httpGet = new HttpGet(url + "?" + query);
		OAuthToken oAuthToken = getOAuthToken();
		if (oAuthToken != null) {
			CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY,
					Constants.CONSUMER_SECRET);
			consumer.setMessageSigner(new HmacSha1MessageSigner());
			consumer.setTokenWithSecret(oAuthToken.getToken(), oAuthToken.getTokenSecret());
			try {
				consumer.sign(httpGet);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// httpGet.setHeader("User-Agent",
		// "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0");
		// httpGet.setHeader("Connection", "close");
		// httpGet.setHeader("Pragma", "no-cache");

		return httpGet;
	}

	protected HttpPost createHttpPost(String url, NameValuePair... nameValuePairs) {
		HttpPost httpPost = new HttpPost(url);
		try {
			httpPost.setEntity(new UrlEncodedFormEntity(stripNulls(nameValuePairs), HTTP.UTF_8));
		} catch (UnsupportedEncodingException e1) {
			throw new IllegalArgumentException("Unable to encode http parameters.");
		}
		return httpPost;
	}

	private List<NameValuePair> stripNulls(NameValuePair... nameValuePairs) {
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		for (int i = 0; i < nameValuePairs.length; i++) {
			NameValuePair param = nameValuePairs[i];
			if (param.getValue() != null) {
				params.add(param);
			}
		}
		return params;
	}

	public abstract OAuthToken getOAuthToken();

	public HttpClient getHttpClient() {
		return httpClient;
	}

}
